package com.ma.a02;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;

import javax.annotation.Resource;
import java.util.Map;

/**
 * @ClassName TestBeanFactory
 * @Author: mayongqiang
 * @DATE 2022/3/29 23:33
 * @Description: BeanFactory
 */

public class TestBeanFactory {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // bean的定义 （class,scope,初始化,销毁...）

        // 1.1、beanDefinition的创建
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.
                genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();

        // 1.2、注册进beanFactory中
        beanFactory.registerBeanDefinition("config", beanDefinition);
        // 发现beanFactory没有解析@Bean的bean   需要工具类去解析注解
        System.out.println("============原生BeanFactory===================");
        for (String name : beanFactory.getBeanDefinitionNames()) {
            System.out.println(name);
        }
        System.out.println("============添加后处理器===================");
        // 1.3、给 beanFactory 添加一些常用的后处理器  beanFactory 会拥有解析注解的扩展功能
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        for (String name : beanFactory.getBeanDefinitionNames()) {
            System.out.println(name);
        }
        // 1.4、BeanFactory 的后处理器 BeanFactoryPostProcessor 主要功能，补充了一些 bean 定义
        Map<String, BeanFactoryPostProcessor> beansOfType =
                beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
        // 1.5、拿到所有的后处理器 执行此处理器
        beansOfType.values().forEach(beanFactoryPostProcessor ->
                beanFactoryPostProcessor.postProcessBeanFactory(beanFactory));
        System.out.println("============执行后处理器===================");
        for (String name : beanFactory.getBeanDefinitionNames()) {
            System.out.println(name);
        }
        System.out.println("==========================================");

        /* beanFactoryPostProcessor : Bean工厂后处理器--主要功能 补充了一些bean的定义 */

// Bean 后处理器, 针对 bean 的生命周期的各个阶段提供扩展, 例如 @Autowired @Resource ...
        // 2.1、没有拿到Bean2 因为没有解析@Autowired -- > AutowiredAnnotationProcessor
        //          @Resource ---> CommonAnnotationProcessor
        //  ！这两个称作bean的后处理器  正对每个bean的生命周期（创建 依赖注入...）提供扩展功能


        Map<String, BeanPostProcessor> beanPostProcessorMap =
                beanFactory.getBeansOfType(BeanPostProcessor.class);
        System.out.println("============");
        // 加入bean后处理器
        beanPostProcessorMap.values().stream().sorted(
                // 加入比较器
                beanFactory.getDependencyComparator()
        ).forEach(beanPostProcessor->{
            System.out.println("----------->"+beanPostProcessor);
            // 可以看到  添加顺序为 AutowiredAnnotationBeanPostProcessor  ， CommonAnnotationBeanPostProcessor@
            beanFactory.addBeanPostProcessor(beanPostProcessor);
        });
        //准备所有单例
        beanFactory.preInstantiateSingletons();
        System.out.println("============");
        System.out.println("=====getInter==  @Autowired生效 =====");
        System.out.println(beanFactory.getBean(Bean1.class).getInter());
        /*
            学到了什么:
            a. beanFactory 不会做的事
                   1. 不会主动调用 BeanFactory 后处理器
                   2. 不会主动添加 Bean 后处理器
                   3. 不会主动初始化单例
                   4. 不会解析beanFactory 还不会解析 ${ } 与 #{ }
            b. bean 后处理器会有排序的逻辑
         */
        System.out.println("Common:" + (Ordered.LOWEST_PRECEDENCE - 3));
        System.out.println("Autowired:" + (Ordered.LOWEST_PRECEDENCE - 2));

    }

    interface Inter {

    }

    @Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }

        @Bean
        public Bean3 bean3() {
            return new Bean3();
        }

        @Bean
        public Bean4 bean4() {
            return new Bean4();
        }
    }

    static class Bean3 implements Inter {

    }

    static class Bean4 implements Inter {

    }

    static class Bean1 {
        private static final Logger log = LoggerFactory.getLogger(Bean1.class);
        @Autowired
        private Bean2 bean2;
        @Autowired
        @Resource(name = "bean4")
        private Inter bean3;

        public Bean1() {
            log.debug("构造 Bean1()");
        }

        public Bean2 getBean2() {
            return bean2;
        }

        public Inter getInter() {
            return bean3;
        }
    }

    static class Bean2 {
        private static final Logger log = LoggerFactory.getLogger(Bean2.class);

        public Bean2() {
            log.debug("构造 Bean2()");
        }
    }
}
